package com.david.mydemo.ctl_thread.service;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@Component
@Slf4j
public class CompletableFutureService {

    private ExecutorService pool = Executors.newFixedThreadPool(10);

    /**
     * 有返回值多线程方法一，匿名实现逻辑
     * <br/>CompletableFuture.supplyAsync()使用默认线程池（ForkJoinPool.commonPool()）的方法
     */
    public void supplyAsyncMethod1() {
        CompletableFuture<String> future_a = CompletableFuture.supplyAsync(() -> {
            log.info(Thread.currentThread() + " anonymousMethod：future_a do something...");
            return "a";
        });
        CompletableFuture<String> future_b = CompletableFuture.supplyAsync(() -> {
            log.info(Thread.currentThread() + " anonymousMethod：future_b do something...");
            return "b";
        });
        CompletableFuture<String> future_c = CompletableFuture.supplyAsync(() -> {
            log.info(Thread.currentThread() + " anonymousMethod：future_c do something...");
            return "c";
        });

        CompletableFuture.allOf(future_a, future_b, future_c).join();

        try {
            log.info("异步获取执行结果：future_a={},future_b={},future_c={}", future_a.get(), future_b.get(), future_c.get());
        } catch (InterruptedException | ExecutionException e) {
            log.error("获取数据异常", e);
        }
    }

    /**
     * 有返回值多线程方法二，调用方法
     * <br/>CompletableFuture.supplyAsync()使用默认线程池（ForkJoinPool.commonPool()）的方法
     */
    public void supplyAsyncMethod2() {
        CompletableFuture<String> future_a = CompletableFuture.supplyAsync(() -> supplyAsyncMethod("a"));
        CompletableFuture<String> future_b = CompletableFuture.supplyAsync(() -> supplyAsyncMethod("b"));
        CompletableFuture<String> future_c = CompletableFuture.supplyAsync(() -> supplyAsyncMethod("c"));

        CompletableFuture.allOf(future_a, future_b, future_c).join();

        try {
            log.info("异步获取执行结果：future_a={},future_b={},future_c={}", future_a.get(), future_b.get(), future_c.get());
        } catch (InterruptedException | ExecutionException e) {
            log.error("获取数据异常", e);
        }
    }

    /**
     * 有返回值多线程方法三，调用方法
     * <br/>CompletableFuture.supplyAsync()使用自定义线程池的方法
     */
    public void supplyAsyncMethod3() {
        CompletableFuture<String> future_a = CompletableFuture.supplyAsync(() -> supplyAsyncMethod("a"), pool);
        CompletableFuture<String> future_b = CompletableFuture.supplyAsync(() -> supplyAsyncMethod("b"), pool);
        CompletableFuture<String> future_c = CompletableFuture.supplyAsync(() -> supplyAsyncMethod("c"), pool);

        CompletableFuture.allOf(future_a, future_b, future_c).join();

        try {
            log.info("异步获取执行结果：future_a={},future_b={},future_c={}", future_a.get(), future_b.get(), future_c.get());
        } catch (InterruptedException | ExecutionException e) {
            log.error("获取数据异常", e);
        }
    }

    /**
     * 无返回值多线程方法一，匿名实现逻辑
     * <br/>CompletableFuture.runAsync()使用默认线程池（ForkJoinPool.commonPool()）的方法
     */
    public void runAsyncMethod1() {
        CompletableFuture<Void> future_a = CompletableFuture.runAsync(() -> {
            log.info(Thread.currentThread() + " anonymousMethod：future_a do something...");
        });
        CompletableFuture<Void> future_b = CompletableFuture.runAsync(() -> {
            log.info(Thread.currentThread() + " anonymousMethod：future_b do something...");
        });
        CompletableFuture<Void> future_c = CompletableFuture.runAsync(() -> {
            log.info(Thread.currentThread() + " anonymousMethod：future_c do something...");
        });

        CompletableFuture.allOf(future_a, future_b, future_c).join();

        try {
            log.info("异步获取执行结果：future_a={},future_b={},future_c={}", future_a.get(), future_b.get(), future_c.get());
        } catch (InterruptedException | ExecutionException e) {
            log.error("获取数据异常", e);
        }
    }

    /**
     * 无返回值多线程方法二，调用方法
     * <br/>CompletableFuture.runAsync()使用默认线程池（ForkJoinPool.commonPool()）的方法
     */
    public void runAsyncMethod2() {
        CompletableFuture<Void> future_a = CompletableFuture.runAsync(() -> runAsyncMethod("a"));
        CompletableFuture<Void> future_b = CompletableFuture.runAsync(() -> runAsyncMethod("b"));
        CompletableFuture<Void> future_c = CompletableFuture.runAsync(() -> runAsyncMethod("c"));

        CompletableFuture.allOf(future_a, future_b, future_c).join();

        try {
            log.info("异步获取执行结果：future_a={},future_b={},future_c={}", future_a.get(), future_b.get(), future_c.get());
        } catch (InterruptedException | ExecutionException e) {
            log.error("获取数据异常", e);
        }
    }

    /**
     * 无返回值多线程方法三，调用方法
     * <br/>CompletableFuture.runAsync()使用自定义线程池的方法
     */
    public void runAsyncMethod3() {
        CompletableFuture<Void> future_a = CompletableFuture.runAsync(() -> runAsyncMethod("a"), pool);
        CompletableFuture<Void> future_b = CompletableFuture.runAsync(() -> runAsyncMethod("b"), pool);
        CompletableFuture<Void> future_c = CompletableFuture.runAsync(() -> runAsyncMethod("c"), pool);

        CompletableFuture.allOf(future_a, future_b, future_c).join();

        try {
            log.info("异步获取执行结果：future_a={},future_b={},future_c={}", future_a.get(), future_b.get(), future_c.get());
        } catch (InterruptedException | ExecutionException e) {
            log.error("获取数据异常", e);
        }
    }

    /**
     * 有返回值异步回调多线程方法一，匿名调用
     * <br/>CompletableFuture.thenApplyAsync()使用默认线程池的方法
     * <br/>使用thenApplyAsync在子任务中是另起一个线程执行任务，并且thenApplyAsync可以自定义线程池，默认的使用ForkJoinPool.commonPool()线程池
     */
    public void thenApplyAsyncMethod1() {
        CompletableFuture<String> future_a = CompletableFuture.supplyAsync(() -> {
            log.info(Thread.currentThread() + " anonymousMethod：future_a do something...");
            return "a";
        });
        CompletableFuture<String> future_b = future_a.thenApplyAsync((result) -> {
            log.info(Thread.currentThread() + " anonymousMethod：future_b do something...");
            result += "b";
            return result;
        });

        try {
            //等待任务1执行完成
            log.info("future_a 结果->" + future_a.get());
            //等待任务2执行完成
            log.info("future_b 结果->" + future_b.get());
        } catch (InterruptedException | ExecutionException e) {
            log.error("获取数据异常", e);
        }
    }

    /**
     * 有返回值异步回调多线程方法二，匿名调用
     * <br/>CompletableFuture.thenApply()使用默认线程池的方法
     * <br/>使用thenApply方法时子任务与父任务使用的是同一个线程
     */
    public void thenApplyMethod2() {
        CompletableFuture<String> future_a = CompletableFuture.supplyAsync(() -> {
            log.info(Thread.currentThread() + " anonymousMethod：future_a do something...");
            return "a";
        });
        CompletableFuture<String> future_b = future_a.thenApply((result) -> {
            log.info(Thread.currentThread() + " anonymousMethod：future_b do something...");
            result += "b";
            return result;
        });

        try {
            //等待任务1执行完成
            log.info("future_a 结果->" + future_a.get());
            //等待任务2执行完成
            log.info("future_b 结果->" + future_b.get());
        } catch (InterruptedException | ExecutionException e) {
            log.error("获取数据异常", e);
        }
    }

    private String supplyAsyncMethod(String param) {
        log.info(Thread.currentThread() + " supplyAsyncMethod: future_method_" + param + " do something...");
        return "return str: " + param;
    }

    private void runAsyncMethod(String param) {
        log.info(Thread.currentThread() + " runAsyncMethod: future_method_" + param + " do something...");
    }


}
